#include "app/app.hpp"
#include "base/StructType.hpp"
#include "config/global_config.hpp"
#include "base/Macro.hpp"
#include "common/FileCommon.hpp"
#include "common/MemCommon.hpp"
#include "common/CellCommon.hpp"
#include "core/page/Page.hpp"
#include "util/Log.hpp"
#include "util/Date.hpp"
#include "sql/Parse.hpp"
#include "core/lock/TransactionManager.hpp"
uint64_t gNexTrxId = 0;

const char* to_string(SqlKind k) {
    switch (k) {
        case SqlKind::Create:  return "Create";
        case SqlKind::Insert:  return "Insert";
        case SqlKind::Update:  return "Update";
        case SqlKind::Select:  return "Select";
        case SqlKind::Delete:  return "Delete";
        case SqlKind::Unknown: return "Unknown";
    }
    return "Unknown";   // 兜底
}

std::string index(const std::string& sqlBatch,Session &session){
    std::vector<std::string> sqlList = splitSqlBySemicolon(sqlBatch);

    for (std::string sql: sqlList) {
        std::cout << sql << std::endl;
        SqlKind kind = detectSqlKind(sql);
        Transaction trx{
            gNexTrxId++,
            TrxStatus::ACTIVE,
            nowMs(),
            0,
            IsolationLevel::READ_COMMITTED,
            };
        // 收集快照， 遍历现有已经开启的事务，并且是激活状态的 存入快照。
        ReadView readView {};
        for (auto& [key, value] : gTrxMgr.mTransaction) {
            if(value.trxStatus == TrxStatus::ACTIVE && trx.startTime > value.startTime){
                readView.activeTrxIds.push_back(value);
            }
        }
        Context context{};
        context.session = &session;
        context.trx = &trx;
        context.readView = &readView;
        context.sqlKind = kind;
        context.sql = sql;
        std::cout << to_string(kind) << std::endl;
        switch (kind) {
            case SqlKind::Create: /* 走建表流程 */createTable(context,sql); break;
            case SqlKind::Insert: /* 走插入流程 */insertRecord(context,sql); break;
            case SqlKind::Update: /* 走更新流程 */updateRecord(context,sql); break;
            case SqlKind::Select: /* 走查询流程 */return readRecordList(context,sql); break;
            case SqlKind::Delete: /* 走删除流程（你暂未实现） */ break;
            default: /* 报不支持/语法错 */return "-12222"; break;
        }
    }

    return "";
}

void initFieldList(std::vector<FieldInfo> &fieldList){
//    files.push_back(FieldInfo{"sqlId",FieldType::INT});
//    files.push_back(FieldInfo{"next",FieldType::INT});
//    files.push_back(FieldInfo{"prev",FieldType::INT});
//    files.push_back(FieldInfo{"transactionId",FieldType::INT});
//    files.push_back(FieldInfo{"rollbackId",FieldType::INT});




    fieldList.insert(fieldList.begin(),FieldInfo{"deleted",FieldType::INT});      // 删除标记：0=未删除，1=已删除
    fieldList.insert(fieldList.begin(),FieldInfo{"offset",FieldType::INT});
    fieldList.insert(fieldList.begin(),FieldInfo{"undoLogOffset",FieldType::INT});
    fieldList.insert(fieldList.begin(),FieldInfo{"transactionId",FieldType::INT});
    fieldList.insert(fieldList.begin(),FieldInfo{"prev",FieldType::INT});
    fieldList.insert(fieldList.begin(),FieldInfo{"next",FieldType::INT});
    fieldList.insert(fieldList.begin(),FieldInfo{"recordId",FieldType::INT});
}

void createTable(Context &context,std::string &sql){
    std::vector<FieldInfo> fieldList;
    std::string tableName;
    parseCreateTableSql(sql,tableName,fieldList);
    initFieldList(fieldList);
    std::string path  = gSystemConfig.dataPath + tableName + ".ibd";
    DataConfig dataConfig{};
    findDataConfig(tableName,dataConfig);
    if(dataConfig.tablePath.empty()){
        dataConfig.tableName = tableName;
        dataConfig.tablePath = path;
        dataConfig.schemaSize = fieldList.size();
        gSystemConfig.dataConfigs.push_back(dataConfig);
        saveAsJson("system_config.json",gSystemConfig);
    }
//    std::cout << "createTable fieldList" << fieldList.size() << std::endl;
//    Log::log(fieldList);
    IbdConfig ibdConfig{};
    ibdConfig.file = std::make_unique<std::fstream>(dataConfig.tablePath,
                                                    std::ios::in | std::ios::out | std::ios::binary);
//    std::fstream file(dataConfig.tablePath, std::ios::in | std::ios::out | std::ios::binary);
    if (!ibdConfig.file->is_open()) {
        // 用 out 模式创建文件
        ibdConfig.file->open(dataConfig.tablePath, std::ios::out | std::ios::binary);
        ibdConfig.file->close();
        // 再用读写模式打开
        ibdConfig.file->open(dataConfig.tablePath, std::ios::in | std::ios::out | std::ios::binary);
    }

    if (!ibdConfig.file->is_open()) {
        std::cerr << "无法打开文件3" << std::endl;
        return;
    }

    std::vector<uint8_t> page(PAGE_SIZE);
    FileHeader fileHeader{};
    fileHeader.lastPage = 0;
    fileHeader.pageCount = FIRST_PAGE_NO;
    fileHeader.schemaCount = fieldList.size();

    memcpy(page.data(),&fileHeader,FILE_HEADER_SIZE);

    int ret = FileCommon::writePage(*ibdConfig.file,FILE_HEADER_NO,page);
    if(ret != 0){
        std::cerr << "createTable writePage is error " << std::endl;
    }
    std::vector<uint8_t> page2(PAGE_SIZE);
    for(size_t i = 0;i<fieldList.size();++i){
        FieldInfo fi = fieldList.at(i);
        std::memcpy(page2.data() + i *sizeof(FieldInfo) , &fieldList[i], sizeof(FieldInfo));
    }
    ret = FileCommon::writePage(*ibdConfig.file,SCHEMA_PAGE_NO,page2);
    if(ret !=0){
        std::cerr << "createTable writePage fieldList is error " << std::endl;
    }

    ibdConfig.fileHeader = fileHeader;
    ibdConfig.fieldInfo = fieldList;
    ibdConfig.name = tableName;
    gTableConfig.insert_or_assign(tableName, std::move(ibdConfig));
}

int insertRecord(Context &context,const std::string &sql){
    std::string table;
    std::vector<Cell> cells;
    std::vector<FieldInfo> schema;
    buildCellsFromInsert(sql, schema, table, cells);
    if(table.empty()){
        std::cerr << "insertRecord table name is emp" << table << std::endl;
        return -1;
    }
    int ret = 0;
    DataConfig dataConfig{};
    findDataConfig(table,dataConfig);
    if (buildCellsFromInsert(sql, gTableConfig[table].fieldInfo, table, cells)) {
        // 这里的 cells 已按 schema 对齐：INT 填 i64，STRING 填 str，DATETIME 填 datetime[5]
//        insertRecord(table, cells); // 你的已有入口
//        Log::log(cells,globalTableConfig[table].fieldInfo);
    }else{
        std::cout << "error22: " << table<< std::endl;
        return -1;
    }
    std::vector<uint8_t> row(PAGE_SIZE);
    PageHead pageHead{};
    // 页目录
    std::vector<uint32_t> slotTmp;
    if(gTableConfig[table].fileHeader.lastPage == 0){
        gTableConfig[table].fileHeader.lastPage = 1;
        Page page(gTableConfig[table].file.get(),&gTableConfig[table].fileHeader, &pageHead,&gTableConfig[table].fieldInfo, &row,&slotTmp);
        page.createPage();
        page.insert(cells);
    }else{
        // 按照索引寻找插入数据的位置
        uint32_t primaryIndex = CellCommon::findFieldPrimaryIndex(gTableConfig[table].fieldInfo);
        uint64_t key = cells.at(primaryIndex).i64;
        Page page = findDataPage(context,table,gTableConfig[table].fileHeader.rootIndexPageNo,key);
        page.insert(cells);
    }

    return 0;
}

int updateRecord(Context &context,const std::string &sql){
    std::string tableName = getTableName(sql);
    context.tableName = tableName;
    std::fstream * file = gTableConfig[tableName].file.get();
    // 读取file header
    FileHeader * fileHeader = &gTableConfig[tableName].fileHeader;
    std::vector<FieldInfo> *fieldInfoList = &gTableConfig[tableName].fieldInfo;


    UpdatePlan updatePlan;
    std::vector<UpdateSetItem> updateSets;
    std::vector<SqlFilter> where;
    buildUpdateSetsAndWhereFromSql(sql,*fieldInfoList,updateSets,where);
    Log::log(tableName);
    Log::log(updateSets,"sets");
    Log::log(where,"where");
    std::fstream * undoLogFile = gTableConfig[UNDO_LOG].file.get();

//    FileCommon::orderWrite(undoLogFile,)
    uint32_t offset = static_cast<uint32_t>(file->tellp());
    std::vector<Page> pages;
    findRecord(context,where,[&pages](Page page){
        pages.push_back(page);
    });

    for (Page page:pages) {
        for (std::vector<Cell> cell: page.mPageData) {
            std::vector<Cell> newCell = cell;
            cell[CELL_INDEX_DELETED].i64 = DELETED;
            uint32_t size = page.cellToVector(cell,page.mPage->data() + cell[CELL_INDEX_OFFSET].i64);
            newCell[CELL_INDEX_TRANSACTION].i64 = context.trx->trxId;
            newCell[CELL_INDEX_UNDO_LOG_OFFSET].i64 = offset;
            newCell[CELL_INDEX_OFFSET].i64 = page.mPageHead.freeOffset;
            // 更新slot
            for (int i = 0; i < page.mSlot.size(); ++i) {
                if(page.mSlot.at(i) == cell[CELL_INDEX_OFFSET].i64){
                    page.mSlot.at(i) = newCell[CELL_INDEX_OFFSET].i64;
                }
            }

            uint32_t slotLen = page.mPageHead.slotSize * sizeof(uint32_t);
            memcpy(page.mPage->data() + PAGE_SIZE - slotLen, page.mSlot.data(), slotLen);

            for (UpdateSetItem updateSetItem: updateSets) {
                newCell[updateSetItem.colIndex] = updateSetItem.value;
            }
            Log::log(newCell,*fieldInfoList,"xx");
            page.cellToVector(newCell,page.mPage->data()+page.mPageHead.freeOffset);

            page.mPageHead.freeOffset += size;
            page.mPageHead.freeSize -=size;
            offset += size;
            if(newCell[CELL_INDEX_PREV].i64 == 0){
                page.mPageHead.firstRecord = newCell[CELL_INDEX_OFFSET].i64;
            }
            if(newCell[CELL_INDEX_NEXT].i64 == 0){
                page.mPageHead.lastRecord = newCell[CELL_INDEX_OFFSET].i64;
            }
            page.updNextOffset(newCell[CELL_INDEX_OFFSET].i64,newCell[CELL_INDEX_PREV].i64);
            page.updPrevOffset(newCell[CELL_INDEX_OFFSET].i64,newCell[CELL_INDEX_NEXT].i64);

        }
        memcpy(page.mPage->data(), &page.mPageHead, PAGE_HEAD_SIZE);
        page.saveAll();
    }

    return 0;
}

bool rowMatch(std::vector<Cell>& row,SqlFilter& f){
    const Cell& c = row[f.colIndex];
    switch (f.value.type) {
        case FieldType::INT:     return c.i64 == f.value.i64;
        case FieldType::STRING:  return c.str == f.value.str;                 // UTF-8 字节比较
        case FieldType::DATETIME:return std::memcmp(c.datetime, f.value.datetime, 5) == 0;
    }
    return false;
}

int findRecord(Context &context,std::vector<SqlFilter> &sqlFilter,const std::function<void(Page)>& callBack){
    int ret = 0;
    std::fstream * file = gTableConfig[context.tableName].file.get();
    // 读取file header
    FileHeader * fileHeader = &gTableConfig[context.tableName].fileHeader;
    // 读取表格配置
    std::vector<FieldInfo> fieldList = gTableConfig[context.tableName].fieldInfo;

    Log::log(sqlFilter,"sql");
    SqlFilter filter1;
    bool found = false;
    for (SqlFilter filter: sqlFilter) {
        if(fieldList.at(filter.colIndex).isPrimary){
            filter1 = filter;
            found = true;
        }
    }
    if(found){
        Page pg = findDataPage(context,context.tableName,fileHeader->rootIndexPageNo,filter1.value.i64);
        auto [ a ,b] = pg.findRecordIndex(filter1.value.i64);
        std::vector<Cell> cells;
        pg.vectorToCell(cells,pg.mPage->data() + pg.mSlot.at(b));
        Log::log(cells,fieldList,"xkk");
        if(cells[CELL_INDEX_DELETED].i64 == UN_DELETED){
            pg.mPageData.push_back(cells);
            callBack(pg);
        }
    }else {
        std::cout << "1111111111111" << std::endl;
        uint64_t pageNo = FIRST_PAGE_NO;
        size_t i = 0;
        while (pageNo != 0 && i < fileHeader->pageCount) {
            i++;
            std::vector<uint8_t> pageList(PAGE_SIZE);
            FileCommon::readPage(*file, pageNo, pageList);

            PageHead pageHead{};
            ret = MemCommon::copyPageHeader(pageList, pageHead, PAGE_HEAD_SIZE);
            if (ret != 0) {
                std::cerr << "copyPageHeader error " << std::endl;
            }
            std::vector<uint32_t> slot(1);
            Page page(file, fileHeader, &pageHead, &fieldList, &pageList, &slot);
            page.mPageData.clear();
            page.readPageAll(pageHead.firstRecord);
            callBack(page);
            pageNo = pageHead.pageNext;
        }
    }
    return ret;
}

std::string readRecordList(Context &context,const std::string &sql){
    std::string tableName = getTableName(sql);
    context.tableName = tableName;
    if(tableName.empty()){
        std::cerr << "readRecordList table name is emp" << tableName << std::endl;
       return "-1";
    }
    int ret = 0;
    std::fstream * file = gTableConfig[tableName].file.get();
    // 读取file header
    FileHeader * fileHeader = &gTableConfig[tableName].fileHeader;
    // 读取表格配置
    std::vector<FieldInfo> fieldList = gTableConfig[tableName].fieldInfo;
//    std::vector<FieldInfo> fieldList(fileHeader->schemaCount);
//    FileCommon::readTableFieldList(*file,fieldList);
    std::vector<SqlFilter> sqlFilter;
    buildWhereFromSelectSql(sql,fieldList,sqlFilter);
    std::vector<std::vector<Cell>> result;


    ret = findRecord(context,sqlFilter,[sqlFilter,&result](Page page){
        std::cout << "22222222222" <<page.mPageData.size() << std::endl;
        if(sqlFilter.empty()){
            result.insert(result.end(),page.mPageData.begin(),page.mPageData.end());
        }else{
            for (auto& one : page.mPageData) {
                std::vector<bool> ret;
                for (SqlFilter filter: sqlFilter) {
                    ret.push_back(rowMatch(one, filter));
//                    if (rowMatch(one, filter)) {
//                        result.push_back(one);
//                    }
                }
                bool has_false = ret.size() == std::count(ret.begin(), ret.end(), true);
                if(has_false){
                    result.push_back(one);
                }

            }
        }
    });
    if(ret != 0 ){
        std::cerr << "readRecordList findRecord is error " << std::endl;
        return "readRecordList findRecord is error";
    }

    std::cout << "22222222222xxxxxx  " <<result.size() << std::endl;
    nlohmann::json j{};
    to_json_array(j,result,fieldList);
    std::cout << "cell toJsonArray: " << j.dump(4) << std::endl;

    return to_string(j);
}